<!-- src/views/admin/SkuList.vue -->
<template>
  <el-card class="sku-list-page">
    <!-- 1. 工具栏：筛选 + 导入导出 + 新增 -->
    <div class="toolbar">
      <!-- SPU 下拉筛选 -->
      <el-select
        v-model="filters.spuId"
        placeholder="选择 SPU"
        filterable
        clearable
        @change="onSearch"
        size="small"
        class="toolbar-item"
        style="width: 200px"
      >
        <el-option
          v-for="s in spuOptions"
          :key="s.id"
          :label="s.title"
          :value="s.id"
        />
      </el-select>
      <!-- 商品下拉筛选 -->
      <el-select
        v-model="filters.productId"
        placeholder="选择商品"
        filterable
        clearable
        @change="onSearch"
        size="small"
        class="toolbar-item"
        style="width: 200px"
      >
        <el-option
          v-for="p in productOptions"
          :key="p.id"
          :label="p.name"
          :value="p.id"
        />
      </el-select>
      <!-- 标题搜索 -->
      <el-input
        v-model="filters.title"
        placeholder="SKU 标题"
        clearable
        @clear="onSearch"
        @keyup.enter="onSearch"
        size="small"
        class="toolbar-item"
        style="width: 200px"
      >
        <template #prefix>
          <el-icon><Search /></el-icon>
        </template>
      </el-input>
      <!-- 上架状态 -->
      <el-select
        v-model="filters.saleable"
        placeholder="上架状态"
        clearable
        @change="onSearch"
        size="small"
        class="toolbar-item"
        style="width: 140px"
      >
        <el-option label="上架" :value="true" />
        <el-option label="下架" :value="false" />
      </el-select>
      <!-- 查询按钮 -->
      <el-button type="primary" size="small" @click="onSearch">查询</el-button>

      <!-- 右侧操作：导出、下载模板、导入、 新增 -->
      <div class="toolbar-actions">
        <el-button size="small" @click="onExport">导出</el-button>
        <el-button size="small" @click="downloadTemplate">下载模板</el-button>
        <el-upload
          :before-upload="beforeImport"
          :show-file-list="false"
          class="upload-import"
        >
          <el-button size="small">导入</el-button>
        </el-upload>
        <el-button type="primary" size="small" @click="openDialog()"
          >新增 SKU</el-button
        >
        <el-button
          type="danger"
          size="small"
          :disabled="!multipleSelection.length"
          @click="onBatchDelete"
          style="margin-left: 16px"
        >
          批量删除
        </el-button>
      </div>
    </div>

    <!-- 2. SKU 表格 -->
    <el-table
      v-loading="loading"
      :data="skus"
      stripe
      @selection-change="onSelectChange"
      style="width: 100%"
    >
      <el-table-column type="selection" width="50" />

      <el-table-column prop="id" label="SKU ID" width="100" align="center" />
      <el-table-column prop="spuTitle" label="SPU 名称" min-width="150" />
      <el-table-column prop="productId" label="商品ID" width="100" align="center" />
      <el-table-column prop="title" label="SKU 标题" min-width="180" />
      <el-table-column prop="skuCode" label="SKU 编码" min-width="140" />
      <el-table-column prop="price" label="价格" width="100" />
      <el-table-column prop="costPrice" label="成本价" width="100" />
      <el-table-column label="库存" width="120" align="center">
        <template #default="{ row }">
          <el-input-number
            v-model="row.stock"
            :min="0"
            :step="1"
            size="small"
            @change="onStockChange(row)"
          />
        </template>
      </el-table-column>
      <el-table-column
        prop="specCombination"
        label="规格组合"
        min-width="180"
      />
      <el-table-column label="图片" width="140" align="center">
        <template #default="{ row }">
          <el-image
            v-if="row.images && row.images.length"
            :src="row.images[0]"
            style="width: 60px; height: 60px"
            fit="cover"
          />
        </template>
      </el-table-column>
      <el-table-column prop="saleable" label="上架" width="100" align="center">
        <template #default="{ row }">
          <el-switch
            v-model="row.saleable"
            :active-value="true"
            :inactive-value="false"
            @change="onToggleSaleable(row, $event)"
            size="small"
          />
        </template>
      </el-table-column>
      <el-table-column prop="valid" label="有效" width="100" align="center">
        <template #default="{ row }">
          <el-switch
            v-model="row.valid"
            :active-value="true"
            :inactive-value="false"
            @change="onToggleValid(row, $event)"
            size="small"
          />
        </template>
      </el-table-column>
      <el-table-column prop="createTime" label="创建时间" width="180" />
      <el-table-column prop="updateTime" label="更新时间" width="180" />

      <el-table-column label="操作" width="180" align="center" fixed="right">
        <template #default="{ row }">
          <div class="action-btns">
            <el-button type="primary" size="small" @click="openDialog(row)">编辑</el-button>
            <el-button type="danger" size="small" @click="onDelete(row)">删除</el-button>
          </div>
        </template>
      </el-table-column>
      <template #empty>
        <el-empty description="暂无数据" />
      </template>
    </el-table>

    <!-- 3. 分页 -->
    <div class="pagination">
      <el-pagination
        background
        layout="prev, pager, next, jumper, sizes, total"
        :current-page="pageNum"
        :page-size="pageSize"
        :page-sizes="[10, 20, 50]"
        :total="total"
        @current-change="onPageChange"
        @size-change="onSizeChange"
      />
    </div>

    <!-- 4. 新增/编辑 弹窗 -->
    <el-dialog :title="dialogTitle" v-model="dialogVisible" width="600px">
      <el-form
        :model="form"
        :rules="formRules"
        ref="formRef"
        label-width="120px"
      >
        <!-- SPU -->
        <el-form-item label="SPU" prop="spuId">
          <el-select
            v-model="form.spuId"
            placeholder="选择 SPU"
            filterable
            clearable
          >
            <el-option
              v-for="s in spuOptions"
              :key="s.id"
              :label="s.title"
              :value="s.id"
            />
          </el-select>
        </el-form-item>
        <!-- 商品 -->
        <el-form-item label="商品" prop="productId">
          <el-select
            v-model="form.productId"
            placeholder="选择商品"
            filterable
            clearable
          >
            <el-option
              v-for="p in productOptions"
              :key="p.id"
              :label="p.name"
              :value="p.id"
            />
          </el-select>
        </el-form-item>
        <!-- 标题 -->
        <el-form-item label="SKU 标题" prop="title">
          <el-input v-model="form.title" autocomplete="off" />
        </el-form-item>
        <!-- SKU 编码 -->
        <el-form-item label="SKU 编码" prop="skuCode">
          <el-input v-model="form.skuCode" autocomplete="off" />
        </el-form-item>
        <!-- 价格 -->
        <el-form-item label="价格" prop="price">
          <el-input-number
            v-model="form.price"
            :min="0"
            :step="0.01"
            style="width: 100%"
          />
        </el-form-item>
        <!-- 成本价 -->
        <el-form-item label="成本价" prop="costPrice">
          <el-input-number
            v-model="form.costPrice"
            :min="0"
            :step="0.01"
            style="width: 100%"
          />
        </el-form-item>
        <!-- 库存 -->
        <el-form-item label="库存" prop="stock">
          <el-input-number
            v-model="form.stock"
            :min="0"
            :step="1"
            style="width: 100%"
          />
        </el-form-item>
        <!-- 规格组合 -->
        <el-form-item label="规格组合" prop="specCombination">
          <el-input
            v-model="form.specCombination"
            placeholder="如 flavor:plain;weight:500"
            autocomplete="off"
          />
        </el-form-item>
        <!-- 图片上传，多图 -->
        <el-form-item label="图片" prop="images">
          <el-upload
            multiple
            :file-list="fileList"
            :http-request="handleImageUpload"
            :before-upload="beforeImageUpload"
            :on-remove="onImageRemove"
            list-type="picture-card"
          >
            <i class="el-icon-plus"></i>
          </el-upload>
          <div class="tip">可上传多张图片，大小不超过 2MB</div>
        </el-form-item>
        <!-- 上架状态 -->
        <el-form-item label="上架" prop="saleable">
          <el-switch
            v-model="form.saleable"
            :active-value="true"
            :inactive-value="false"
            active-text="上架"
            inactive-text="下架"
          />
        </el-form-item>
        <!-- 有效 -->
        <el-form-item label="有效" prop="valid">
          <el-switch
            v-model="form.valid"
            :active-value="true"
            :inactive-value="false"
            active-text="有效"
            inactive-text="无效"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="dialogLoading" @click="submitForm">
          确定
        </el-button>
      </template>
    </el-dialog>
  </el-card>
</template>
  
<script setup>
import { ref, reactive, onMounted, computed, watch } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import {
  pageSku,
  getSku,
  addSku,
  updateSku,
  deleteSku,
  exportSku,
  downloadSkuTemplate,
  importSku,
  updateSkuStock,
} from "@/api/productSku"; // 根据项目实际路径调整
import { pageSpu } from "@/api/productSpu"; // SPU 列表，用于筛选下拉
import { pageProducts } from "@/api/products"; // 商品列表，用于筛选下拉
import { Search } from "@element-plus/icons-vue";

// 列表状态
const loading = ref(false);
const skus = ref([]);
const total = ref(0);
const pageNum = ref(1);
const pageSize = ref(10);
const multipleSelection = ref([]);

// 筛选条件
const filters = reactive({
  spuId: null,
  productId: null,
  title: "",
  saleable: null, // Boolean
});

// SPU 下拉选项
const spuOptions = ref([]);
// 商品下拉选项
const productOptions = ref([]);

// 查询 SKU 列表
async function fetchList() {
  loading.value = true;
  try {
    const params = {
      pageNum: pageNum.value,
      pageSize: pageSize.value,
      ...(filters.spuId ? { spuId: filters.spuId } : {}),
      ...(filters.productId ? { productId: filters.productId } : {}),
      ...(filters.title ? { title: filters.title } : {}),
      ...(filters.saleable !== null ? { saleable: filters.saleable } : {}),
    };
    const res = await pageSku(params);
    const data = res.data;
    // data.items: SkuVO[], data.total
    skus.value = data.items || [];
    total.value = data.total || 0;
  } catch (err) {
    console.error("查询 SKU 列表失败", err);
  } finally {
    loading.value = false;
  }
}

// 加载 SPU 列表（用于筛选下拉）
async function loadSpus() {
  try {
    // 假设一次性加载所有 SPU（若 SPU 很多，可改为搜索联动）
    const res = await pageSpu({
      pageNum: 1,
      pageSize: 100,
      name: "",
      status: null,
    });
    spuOptions.value = res.data.items || [];
  } catch (err) {
    console.error("加载 SPU 列表失败", err);
  }
}

// 加载商品列表（用于筛选下拉）
async function loadProducts() {
  try {
    const res = await pageProducts({
      pageNum: 1,
      pageSize: 100,
      name: "",
      status: null,
    });
    productOptions.value = res.data.items || [];
  } catch (err) {
    console.error("加载商品列表失败", err);
  }
}

// 搜索按钮
function onSearch() {
  pageNum.value = 1;
  fetchList();
}

// 分页回调
function onPageChange(page) {
  pageNum.value = page;
  fetchList();
}
function onSizeChange(size) {
  pageSize.value = size;
  pageNum.value = 1;
  fetchList();
}

// 选择行
function onSelectChange(val) {
  multipleSelection.value = val;
}

// 导出
async function onExport() {
  try {
    const res = await exportSku();
    // 假设后端返回二进制流
    const blob = new Blob([res], {
      type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "sku_list.xlsx";
    a.click();
    window.URL.revokeObjectURL(url);
  } catch (err) {
    console.error("导出失败", err);
  }
}
// 下载模板
async function downloadTemplate() {
  try {
    const res = await downloadSkuTemplate();
    const blob = new Blob([res], {
      type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "sku_template.xlsx";
    a.click();
    window.URL.revokeObjectURL(url);
  } catch (err) {
    console.error("下载模板失败", err);
  }
}
// 导入前拦截
function beforeImport(file) {
  importSku(file)
    .then(() => {
      ElMessage.success("导入成功");
      fetchList();
    })
    .catch((err) => {
      console.error("导入失败", err);
      ElMessage.error("导入失败");
    });
  return false; // 阻止 el-upload 自动上传，使用自定义调用
}

// 删除单条
function onDelete(row) {
  ElMessageBox.confirm("确认删除该 SKU？", "提示", { type: "warning" }).then(
    async () => {
      try {
        // deleteSku 接口假设接受数组
        await deleteSku([row.id]);
        ElMessage.success("删除成功");
        fetchList();
      } catch (err) {
        console.error("删除失败", err);
      }
    }
  );
}

// 处理库存变化
const onStockChange = async (row) => {
  try {
    await updateSkuStock(row.id, row.stock);
    ElMessage.success('库存更新成功！');
  } catch (error) {
    ElMessage.error('库存更新失败：' + (error.message || '未知错误'));
    
    fetchList();
  }
};

// 批量删除
const onBatchDelete = async () => {
  if (!multipleSelection.value.length) return;
  const ids = multipleSelection.value.map((i) => i.id);
  try {
    await deleteSku(ids);
    ElMessage.success("批量删除成功");
    multipleSelection.value = [];
    fetchList();
  } catch (err) {
    console.error("批量删除失败", err);
  }
};

// 切换上架状态（如果后端提供切换接口，可替换下面逻辑）
// 这里假设 updateSku 可以更新 saleable 字段；如果后端有专门接口也可调用
async function onToggleSaleable(row, newVal) {
  try {
    const dto = {
      id: row.id,
      spuId: row.spuId,
      productId: row.productId,
      title: row.title,
      skuCode: row.skuCode,
      images: JSON.stringify(row.images || []),
      price: row.price,
      costPrice: row.costPrice,
      specCombination: row.specCombination,
      saleable: newVal,
      valid: row.valid,
    };
    await updateSku(dto);
    ElMessage.success("上架状态更新成功");
  } catch (err) {
    // 回滚
    row.saleable = !newVal;
    console.error("更新上架状态失败", err);
  }
}
// 切换有效状态
async function onToggleValid(row, newVal) {
  try {
    const dto = {
      id: row.id,
      spuId: row.spuId,
      productId: row.productId,
      title: row.title,
      skuCode: row.skuCode,
      images: JSON.stringify(row.images || []),
      price: row.price,
      costPrice: row.costPrice,
      specCombination: row.specCombination,
      saleable: row.saleable,
      valid: newVal,
    };
    await updateSku(dto);
    ElMessage.success("有效状态更新成功");
  } catch (err) {
    row.valid = !newVal;
    console.error("更新有效状态失败", err);
  }
}

// 新增/编辑 弹窗
const dialogVisible = ref(false);
const dialogTitle = ref("新增 SKU");
const dialogLoading = ref(false);
const formRef = ref(null);
// 表单数据
const form = reactive({
  id: null,
  spuId: null,
  productId: null,
  title: "",
  skuCode: "",
  imagesArray: [], // 前端存储图片 URL 数组
  price: null,
  costPrice: null,
  specCombination: "",
  stock: null,
  saleable: true,
  valid: true,
});
// el-upload 图片 fileList
const fileList = ref([]);

// 表单校验规则
const formRules = {
  spuId: [{ required: true, message: "请选择 SPU", trigger: "change" }],
  productId: [{ required: true, message: "请选择商品", trigger: "change" }],
  title: [{ required: true, message: "请输入 SKU 标题", trigger: "blur" }],
  price: [{ required: true, message: "请输入价格", trigger: "change" }],
  stock: [{ required: true, message: "请输入库存", trigger: "change" }],
  saleable: [{ required: true, message: "请选择上架状态", trigger: "change" }],
  valid: [{ required: true, message: "请选择有效状态", trigger: "change" }],
};

// 打开弹窗：row 为选中行或者空
async function openDialog(row) {
  if (row) {
    dialogTitle.value = "编辑 SKU";
    // 加载详情
    try {
      const res = await getSku(row.id);
      const d = res.data;
      form.id = d.id;
      form.spuId = d.spuId;
      form.productId = d.productId;
      form.title = d.title;
      form.skuCode = d.skuCode;
      form.price = d.price;
      form.costPrice = d.costPrice;
      form.specCombination = d.specCombination;
      form.saleable = d.saleable;
      form.valid = d.valid;
      form.stock = d.stock;
      // images: array of URL strings
      form.imagesArray = Array.isArray(d.images) ? [...d.images] : [];
      // 构造 fileList 以在 el-upload 中显示已上传图片
      fileList.value = form.imagesArray.map((url, idx) => ({
        name: `img-${idx}`,
        url,
      }));
    } catch (err) {
      console.error("获取 SKU 详情失败", err);
    }
  } else {
    dialogTitle.value = "新增 SKU";
    form.id = null;
    form.spuId = null;
    form.productId = null;
    form.title = "";
    form.skuCode = "";
    form.price = null;
    form.costPrice = null;
    form.specCombination = "";
    form.stock = 0;
    form.saleable = true;
    form.valid = true;
    form.imagesArray = [];
    fileList.value = [];
  }
  dialogVisible.value = true;
}

// 提交表单
function submitForm() {
  formRef.value.validate(async (valid) => {
    if (!valid) return;
    dialogLoading.value = true;
    try {
      const dto = {
        // id 仅在编辑时
        ...(form.id ? { id: form.id } : {}),
        spuId: form.spuId,
        productId: form.productId,
        title: form.title,
        skuCode: form.skuCode,
        images: JSON.stringify(form.imagesArray),
        price: form.price,
        costPrice: form.costPrice,
        specCombination: form.specCombination,
        stock: form.stock,
        saleable: form.saleable,
        valid: form.valid,
      };
      if (form.id) {
        await updateSku(dto);
        ElMessage.success("更新成功");
      } else {
        await addSku(dto);
        ElMessage.success("新增成功");
      }
      dialogVisible.value = false;
      fetchList();
    } catch (err) {
      console.error("保存 SKU 失败", err);
      ElMessage.error("保存失败");
    } finally {
      dialogLoading.value = false;
    }
  });
}

// 处理图片上传：调用后端通用上传接口，
import { uploadFile } from "@/api/common"; // 根据实际调整
async function handleImageUpload(option) {
  // option: { file, onSuccess, onError }
  const formData = new FormData();
  formData.append("file", option.file);
  try {
    const res = await uploadFile(formData);
    const url = res.data;
    // 添加到 imagesArray
    form.imagesArray.push(url);
    // 更新 fileList：option.file 对象可能需要赋予 url 字段
    option.onSuccess(res.data);
    // 由于 Element Plus el-upload 在 picture-card 模式需要 file 对象拥有 url
    fileList.value.push({
      name: option.file.name,
      url,
    });
    ElMessage.success("上传成功");
  } catch (err) {
    console.error("上传失败", err);
    option.onError(err);
    ElMessage.error("上传失败");
  }
}
// 上传前校验
function beforeImageUpload(file) {
  const isImage = file.type.startsWith("image/");
  const isLt2M = file.size / 1024 / 1024 < 2;
  if (!isImage) {
    ElMessage.error("上传图片须为图片格式");
  }
  if (!isLt2M) {
    ElMessage.error("上传图片大小不能超过 2MB");
  }
  return isImage && isLt2M;
}
// 移除已上传图片
function onImageRemove(file, fileListParam) {
  // file.url 是图片 URL
  const url = file.url;
  const idx = form.imagesArray.findIndex((u) => u === url);
  if (idx >= 0) {
    form.imagesArray.splice(idx, 1);
  }
  // fileList 已由 el-upload 自动更新
}

// 组件挂载时加载数据
onMounted(async () => {
  await loadSpus();
  await loadProducts();
  fetchList();
});
</script>
  
<style scoped>
.sku-list-page {
  padding: 32px 16px 24px 16px;
  background: linear-gradient(135deg, #f8fafc 0%, #f0f4f8 100%);
  border-radius: 18px;
  box-shadow: 0 6px 32px 0 rgba(80,120,200,0.08);
  min-height: 90vh;
  transition: box-shadow 0.3s;
}
.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-bottom: 24px;
  background: rgba(255,255,255,0.85);
  border-radius: 14px;
  box-shadow: 0 2px 12px 0 rgba(80,120,200,0.06);
  padding: 18px 18px 10px 18px;
  animation: fadeInDown 0.7s;
}
@keyframes fadeInDown {
  from { opacity: 0; transform: translateY(-20px); }
  to { opacity: 1; transform: none; }
}
.toolbar-item {
  width: 200px;
  min-width: 120px;
  transition: box-shadow 0.2s, border-color 0.2s;
}
.toolbar-item .el-input__wrapper,
.toolbar-item .el-select__wrapper {
  border-radius: 8px;
  box-shadow: 0 1px 4px 0 rgba(80,120,200,0.04);
}
.toolbar-item .el-input__wrapper:hover,
.toolbar-item .el-select__wrapper:hover {
  border-color: #6c8cff;
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.10);
}
.toolbar-actions {
  margin-left: auto;
  display: flex;
  gap: 12px;
  align-items: center;
}
.el-button[type="primary"] {
  background: linear-gradient(90deg, #6c8cff 0%, #88e0ef 100%);
  border: none;
  color: #fff;
  font-weight: 500;
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.10);
  transition: background 0.2s, box-shadow 0.2s;
}
.el-button[type="primary"]:hover {
  background: linear-gradient(90deg, #88e0ef 0%, #6c8cff 100%);
  color: #fff;
}
.el-button[type="danger"] {
  background: linear-gradient(90deg, #ff6c6c 0%, #ffb88c 100%);
  border: none;
  color: #fff;
  font-weight: 500;
  box-shadow: 0 2px 8px 0 rgba(255,108,108,0.10);
  transition: background 0.2s, box-shadow 0.2s;
}
.el-button[type="danger"]:hover {
  background: linear-gradient(90deg, #ffb88c 0%, #ff6c6c 100%);
  color: #fff;
}
.action-btns {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 14px;
  min-width: 120px;
}
.el-table {
  border-radius: 14px;
  overflow: hidden;
  background: rgba(255,255,255,0.98);
  box-shadow: 0 2px 16px 0 rgba(80,120,200,0.07);
  animation: fadeIn 0.7s;
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.el-table th {
  background: linear-gradient(90deg, #f0f4ff 0%, #f8fafc 100%);
  color: #4a5a7a;
  font-weight: 600;
  font-size: 15px;
}
.el-table tr {
  transition: background 0.2s;
}
.el-table tr:hover {
  background: #eaf3ff !important;
}
.el-table .el-table__row.selected {
  background: #d6e4ff !important;
}
.el-table .el-button {
  border-radius: 8px;
  font-size: 15px;
  min-width: 64px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 2px;
  box-shadow: 0 1px 4px 0 rgba(80,120,200,0.08);
  transition: background 0.2s, transform 0.2s;
}
.el-table .el-button:hover {
  background: linear-gradient(90deg, #6c8cff 0%, #88e0ef 100%);
  color: #fff;
  transform: scale(1.08);
}
.el-table .el-image {
  border-radius: 10px;
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.10);
  border: 1.5px solid #e4e7ed;
  background: #fff;
}
.upload-import {
  display: inline-block;
}
.tip {
  margin-top: 4px;
  color: #909399;
  font-size: 12px;
}
.image-preview img {
  border: 2px solid #e4e7ed;
  border-radius: 8px;
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.10);
}
.pagination {
  text-align: center;
  margin-top: 24px;
}
.el-pagination {
  border-radius: 10px;
  background: rgba(255,255,255,0.85);
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.06);
  padding: 8px 16px;
}
.el-dialog {
  border-radius: 18px !important;
  box-shadow: 0 8px 40px 0 rgba(80,120,200,0.18) !important;
  animation: fadeInUp 0.5s;
}
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(40px); }
  to { opacity: 1; transform: none; }
}
.el-dialog__header {
  font-size: 22px;
  font-weight: 700;
  color: #3a4a6a;
  letter-spacing: 1px;
}
.el-dialog__footer {
  background: #f8fafc;
  border-radius: 0 0 18px 18px;
  padding: 18px 24px;
}
.el-form-item__label {
  font-weight: 600;
  color: #3a4a6a;
  font-size: 15px;
}
.el-form-item .el-input__wrapper,
.el-form-item .el-select__wrapper {
  border-radius: 8px;
  box-shadow: 0 1px 4px 0 rgba(80,120,200,0.04);
  transition: box-shadow 0.2s, border-color 0.2s;
}
.el-form-item .el-input__wrapper:focus-within,
.el-form-item .el-select__wrapper:focus-within {
  border-color: #6c8cff;
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.10);
}
/* 响应式 */
@media screen and (max-width: 1024px) {
  .sku-list-page {
    padding: 8px 2px 12px 2px;
  }
  .toolbar {
    flex-direction: column;
    gap: 10px;
    padding: 12px 8px 6px 8px;
  }
  .action-btns {
    min-width: 80px;
  }
  .el-table th, .el-table td {
    font-size: 13px;
  }
}
@media screen and (max-width: 768px) {
  .sku-list-page {
    padding: 2px 0 6px 0;
    min-height: unset;
  }
  .toolbar {
    flex-direction: column;
    gap: 8px;
    padding: 8px 2px 4px 2px;
  }
  .toolbar-item {
    min-width: 90px;
    width: 100%;
  }
  .el-table th, .el-table td {
    font-size: 12px;
    padding: 4px 2px;
  }
  .el-dialog {
    width: 98vw !important;
    min-width: unset;
    padding: 0;
  }
}
</style>
  